home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / OSAX Samples / ScriptIt OSAX / ScriptOSAX.c < prev    next >
Encoding:
Text File  |  1993-01-30  |  32.6 KB  |  1,098 lines  |  [TEXT/MPS ]

  1. ///////////////////////////////////////////////////////////
  2. //
  3. //      ScriptOSAX.c written by Donald Olson
  4. //        Copyright ®1992-3 Apple Computer Inc.
  5. //        All rights reserved.
  6. //      
  7. //        The ScriptEditor OSAX. This is just a little sample
  8. //        that demonstrates how to read and write script files.
  9. //        It also executes scripts from inside the editor dialog
  10. //        or it can execute scripts with out displaying the dialog.
  11. //
  12. //        As always, bugs and comments to me at D.OLSON on Apple
  13. //        Link.
  14. //        
  15. //        To execute from Toy Surprise:
  16. //         ScriptIt [filepath] [execute only true | false]
  17. //        
  18. //        WARNINGS!!!
  19. //        This is untested code. I mean, I know it works
  20. //        but it's ugly! Scripts and comments are limited to 255
  21. //        characters. I didn't feel like adding TEdit to this thing.
  22. //        
  23. //        Thanks to Theresa, Matt, and Jessica. My wife and kids.
  24. //        Living with a programmer can be a chore sometimes!
  25. //
  26. //        History:
  27. //      12/27/92     First pass
  28. //        12/30/92     Fixed a few bugs
  29. //        1/8/93        Commented a bit more
  30. //        1/30/93        Kick it out into the cruel world.
  31. //
  32. //        To Build:
  33. //        C -b "ScriptOSAX.c" -d SystemSevenOrLater 
  34. //        Rez -a -o "ScriptIt OSAX" -t osax -c ascr 'ScriptOSAX.r'
  35. //        Link -p -w -t osax -c ascr -rt osax=4000 -m SCRIPTITENTRY -sg "AEVTaevtscpt" -ra "AEVTaevtscpt"=resSysHeap,resLocked ∂
  36. //            "ScriptOSAX.c.o" ∂
  37. //            "{CLibraries}"StdCLib.o ∂
  38. //            "{Libraries}"Runtime.o ∂
  39. //            "{Libraries}"Interface.o ∂
  40. //            -o "ScriptIt OSAX" 
  41. //
  42. ///////////////////////////////////////////////////////////
  43.  
  44. #include <Errors.h>
  45. #include <Dialogs.h>
  46. #include <Memory.h>
  47. #include <Fonts.h>
  48. #include <OSEvents.h>
  49. #include <Menus.h>
  50. #include <Processes.h>
  51. #include <String.h>
  52. #include <Resources.h>
  53. #include <Packages.h>
  54. #include <Quickdraw.h>
  55. #ifdef THINK_C
  56.     #include <pascal.h>
  57. #endif
  58. #include <AppleEvents.h>
  59. #include <StandardFile.h>
  60. #include <Aliases.h>
  61. #include <Finder.h>
  62. #include <Files.h>
  63. #include <QDOffscreen.h>
  64. #include <ToolUtils.h>
  65. #include "OSA.h"
  66.                         
  67.  
  68. #define    kMYEDITDIALOG            1112    // Dialog id
  69. #define kSenceOfDecorum            15        // Just above center please
  70. #define kMySPutRsrc                1111    // Custom put dialog
  71.  
  72. #define keyJustExecute            'doit'    // execute only parameter
  73. #define kCommentResType         'TEXT'
  74. #define kStyleResType             'styl'    // We don't use this since 
  75.                                         // we don't do styled text
  76.  
  77. #define kToySurprise            'ToyS'    // Script file creator
  78. #define kCompiledScript            'osas'    // Script file type for 
  79.                                         // compiled scripts
  80. #define kTextScript                'TEXT'    // Script file type for 
  81.                                         // text scripts
  82.  
  83. #define    kOk                 1                // Our dialog items
  84. #define    kCancel             2
  85. #define    kExecute        3
  86. #define    kSaveAs             4
  87. #define    kCommentField     6
  88. #define kScriptField    5
  89. #define kResultField    7
  90. #define kCycleAgain        10
  91.  
  92. #define kSaveCompiled      15                // Items for our custom sfput
  93. #define kSaveText        14
  94.  
  95. #define kScriptRezID    128                // script rez id's
  96. #define kCommentRezID    1128
  97. #define kStyleID        1128
  98.  
  99.  
  100.  
  101. ///////////////////////////////////////////////////////////
  102. //
  103. //     ScriptItEntry()
  104. //    This is the main entry point for the ScriptIt OSAX. 
  105. //    
  106. ///////////////////////////////////////////////////////////
  107.  
  108. pascal OSErr ScriptItEntry(AppleEvent *theEvent, AppleEvent *theReply, long *theRefCon)
  109. {    
  110.     #pragma unused  (theRefCon)
  111.     
  112.     /* Our function prototypes */
  113.     pascal     Boolean MyDlgFilter(DialogPtr theDlg, EventRecord *theEventRec, short *itemHit);
  114.     Rect     ReturnScreenRect(void);
  115.     void     CenterWindow(DialogPtr theDialog);
  116.     OSErr    EditScript(    FSSpec theFileToEdit, Boolean directObjectFound);
  117.     OSErr    ExecuteScript(    FSSpec theFileToExecute, AEDesc *result);
  118.     OSErr    AddFileToDesc(FSSpec theFSSpec, AEDesc *theDesc);
  119.     pascal     short mySFPHook(short item, DialogPtr theDialog, void *myData);
  120.     Boolean DoSave(Boolean *SaveAsCompiled, Str255 scriptName, FSSpec *theFileToEdit);
  121.     OSErr    AddDescToFile(FSSpec theFSSpec, AEDesc theDesc);
  122.     OSErr     DisplayScriptFromFile(    FSSpec theFileToEdit, DialogPtr theDialog, 
  123.                                     ComponentInstance gASComponent,Boolean *SaveAsCompiled);
  124.     OSAError CompileScript(DialogPtr theDialog, ComponentInstance gASComponent, AEDesc source, OSAID *resultingID);
  125.     
  126.     /* variables */
  127.     OSErr                    theErr = noErr;
  128.     Handle                    tempRezHdl = nil;
  129.     FSSpec                    theFileToEdit;
  130.     DescType                typeCode;
  131.     Size                    actualSize;
  132.     Boolean                    directObjectFound = true,
  133.                             justExecute = false;
  134.     AEDesc                     result;
  135.     
  136.     // Init dataHandle for dispose test later    
  137.     result.dataHandle = nil;
  138.     
  139.     // Get the file spec of the file to edit or execute
  140.     
  141.     theErr = AEGetParamPtr(    theEvent,
  142.                             keyDirectObject,
  143.                             typeFSS,
  144.                             &typeCode,
  145.                             (Ptr)&theFileToEdit,
  146.                             sizeof(theFileToEdit),
  147.                             &actualSize);
  148.     
  149.     if((theErr == errAEDescNotFound) || (theErr != noErr)) {
  150.         directObjectFound = false;        // If true, we're editing a script so
  151.                                         // display it
  152.     }
  153.     
  154.     // Get the optional execute only flag
  155.     
  156.     theErr = AEGetParamPtr(    theEvent,
  157.                             keyJustExecute,
  158.                             typeBoolean,
  159.                             &typeCode,
  160.                             (Ptr)&justExecute,
  161.                             sizeof(justExecute),
  162.                             &actualSize);
  163.     
  164.     if(theErr != noErr) justExecute = false;
  165.     
  166.     if(justExecute && (directObjectFound == true))
  167.         theErr = ExecuteScript(theFileToEdit, &result);    // just execute
  168.     else {
  169.         /* Set up our dialog */
  170.         /* Check for availability if our resource */
  171.         
  172.         tempRezHdl = Get1Resource('DLOG', kMYEDITDIALOG);    
  173.         if(tempRezHdl == nil)
  174.             return resNotFound;
  175.         
  176.         /* Do that interact with user thang */ 
  177.         
  178.         theErr = AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  179.         if(theErr != noErr)
  180.         {
  181.             if(tempRezHdl != nil)
  182.                 ReleaseResource(tempRezHdl);        // Set me free
  183.             return theErr;
  184.         }
  185.         
  186.         // Now edit or create a script
  187.         theErr = EditScript(theFileToEdit, directObjectFound);
  188.         
  189.         if(tempRezHdl != nil)
  190.             ReleaseResource(tempRezHdl);    
  191.     }
  192.     if(result.dataHandle != nil)            // Clean up
  193.         AEPutParamDesc(theReply, keyDirectObject, &result);
  194.     return theErr;
  195. }
  196.  
  197. ///////////////////////////////////////////////////////////////////////////////
  198. //
  199. //    AddFileToDesc
  200. //    Takes the descriptor passed in and adds the data found in the FSSpec to it.
  201. //    This is for text scripts.
  202. //    
  203. ///////////////////////////////////////////////////////////////////////////////
  204.  
  205. OSErr    AddFileToDesc(FSSpec theFSSpec, AEDesc *theDesc)
  206. {
  207.     CInfoPBPtr        pb = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  208.        HFileInfo        *fpb = (HFileInfo*)pb;
  209.        long            fileSize = 0;
  210.        Handle            tempBuffer;
  211.     short             fRefNum = 0;
  212.     OSErr            theErr = noErr;
  213.     /* 
  214.         Need to know the size of the file so we can create a buffer large enough to contain the
  215.         file.
  216.     */
  217.     
  218.     /* Set up pblock */
  219.     (*pb).hFileInfo.ioNamePtr = (StringPtr)&(theFSSpec.name);
  220.     (*pb).hFileInfo.ioDirID = theFSSpec.parID;                    
  221.     (*pb).hFileInfo.ioVRefNum = theFSSpec.vRefNum;
  222.     theErr = PBGetCatInfo(pb, false);
  223.     
  224.     if(theErr == noErr) {
  225.         // Make sure we really got a file
  226.         if(fpb->ioFlAttrib & 16) {
  227.             theErr = 3030;
  228.             goto DISPOSELABEL;
  229.         }
  230.     }
  231.     else
  232.         goto DISPOSELABEL;
  233.     fileSize = fpb->ioFlLgLen;
  234.     tempBuffer = NewHandleClear(fileSize);
  235.     if(tempBuffer == nil) {
  236.         theErr = memFullErr;
  237.         goto DISPOSELABEL;
  238.     }
  239.     
  240.     theErr = FSpOpenDF(&theFSSpec, 0, &fRefNum);        // Open data fork
  241.     if(theErr != noErr) goto DISPOSELABEL;
  242.     
  243.     HLock(tempBuffer);    
  244.     theErr = FSRead(fRefNum, &fileSize, *tempBuffer);    // Read in data to buffer
  245.        if(theErr != noErr)  goto DISPOSELABEL;
  246.     
  247.     theErr = FSClose(fRefNum);                            // Close data fork
  248.     if(theErr != noErr) goto DISPOSELABEL;
  249.     
  250.     // Add the data to our descriptor
  251.     theErr = AECreateDesc(typeChar, (Ptr) *tempBuffer, fileSize, theDesc);
  252.      
  253.     DISPOSELABEL:;
  254.     HUnlock(tempBuffer);                             
  255.     DisposHandle(tempBuffer);
  256.     DisposPtr((Ptr)pb);
  257.     
  258.     return theErr;
  259. }
  260.  
  261. ///////////////////////////////////////////////////////////////////////////////
  262. //
  263. //    AddDescToFile
  264. //  This writes the text in an AEDesc to a data file found at the FSSpec.
  265. //    Used to write text scripts to disk
  266. //    
  267. ///////////////////////////////////////////////////////////////////////////////
  268.  
  269. OSErr    AddDescToFile(FSSpec theFSSpec, AEDesc theDesc)
  270. {
  271.        long            fileSize = 0;
  272.     short             fRefNum = 0;
  273.     OSErr            theErr = noErr;
  274.     /* 
  275.         Need to know the size of the descriptor
  276.         file.
  277.     */
  278.     
  279.     fileSize = GetHandleSize(theDesc.dataHandle);
  280.         
  281.     theErr = FSpOpenDF(&theFSSpec, 0, &fRefNum);
  282.     if(theErr != noErr) goto DISPOSELABEL;
  283.  
  284.     HLock(theDesc.dataHandle);    
  285.  
  286.     theErr = FSWrite(fRefNum, &fileSize, *(theDesc.dataHandle));
  287.     if(theErr != noErr) goto DISPOSELABEL;
  288.     
  289.     theErr = FSClose(fRefNum);
  290.     if(theErr != noErr) goto DISPOSELABEL;
  291.      
  292.     DISPOSELABEL:;
  293.     HUnlock(theDesc.dataHandle);                             
  294.     return theErr;
  295. }
  296.  
  297. ///////////////////////////////////////////////////////////////////////////////
  298. //
  299. //    ExecuteScript
  300. //  Execute only, no dialog here!
  301. //    
  302. ///////////////////////////////////////////////////////////////////////////////
  303.  
  304. OSErr    ExecuteScript(FSSpec theFileToExecute, AEDesc *result)
  305. {
  306.     OSAError                 theOSAErr = noErr;
  307.     OSErr                    theErr = noErr;
  308.     OSAID                    resultingID = 0;
  309.     long                    modeFlags = 0;
  310.     Handle                    tempHandle = nil;
  311.     AEDesc                    source;
  312.     short                    ourFileRef, curResFile;
  313.     ComponentInstance        gASComponent = 0;
  314.     
  315.     // open generic component
  316.     
  317.     gASComponent = OpenDefaultComponent(kOSAComponentType, kOSAGenericScriptingComponentSubtype);
  318.     
  319.     // Check errors here!! 
  320.     if((gASComponent == badComponentInstance) || (gASComponent == badComponentSelector))
  321.         return invalidComponentID;     // Is this the right error??
  322.         
  323.     curResFile = CurResFile();        // Save current res chain
  324.     
  325.     // Open our resource file  for reading
  326.     ourFileRef = FSpOpenResFile(&theFileToExecute, fsRdWrPerm);
  327.     if(ResError())
  328.         return ResError();
  329.     
  330.     UseResFile(ourFileRef);
  331.     
  332.     // Get our resource handle
  333.     tempHandle = Get1Resource(kOSAScriptResourceType, kScriptRezID);
  334.     if(tempHandle == nil)
  335.     {
  336.         theErr = AddFileToDesc(theFileToExecute, &source);
  337.         if(theErr == noErr) {
  338.             theOSAErr = OSACompileExecute(    gASComponent,
  339.                                             &source,
  340.                                             kOSANullScript,
  341.                                             modeFlags,
  342.                                             &resultingID);
  343.             
  344.             if(theOSAErr == noErr){
  345.                 /*  
  346.                     Must use OSACoerceToDesc instead of OSADisplay
  347.                     here since we want to preserve the data type 
  348.                     returned from the execution.
  349.                 */
  350.                 theOSAErr = OSACoerceToDesc(    gASComponent,
  351.                                                 resultingID,
  352.                                                 typeWildCard,
  353.                                                 modeFlags,
  354.                                                 result);
  355.             }
  356.                                     
  357.             theErr = theOSAErr;
  358.         }
  359.     }
  360.     else {
  361.         DetachResource(tempHandle);
  362.         
  363.         // Put our text into an AEDesc
  364.         theErr = AECreateDesc(    kOSAScriptResourceType, (Ptr)*tempHandle, 
  365.                                 (Size)(GetHandleSize(tempHandle)), &source);
  366.         if(theErr != noErr) {
  367.             theErr = theOSAErr;
  368.             goto BAILLABEL;
  369.         }
  370.         
  371.         theOSAErr = OSALoadExecute(gASComponent,
  372.                                     &source,
  373.                                     kOSANullScript,
  374.                                     modeFlags,
  375.                                     &resultingID);
  376.         if(theOSAErr != noErr){
  377.             theErr = theOSAErr;
  378.             goto BAILLABEL;
  379.         }
  380.         else  {
  381.             theOSAErr = OSACoerceToDesc(    gASComponent,
  382.                                     resultingID,
  383.                                     typeWildCard,
  384.                                     modeFlags,
  385.                                     result);
  386.         }
  387.                                     
  388.         theErr = theOSAErr;
  389.     }    
  390.     BAILLABEL:;
  391.     // Clean up time
  392.     if(resultingID != 0) OSADispose( gASComponent, resultingID);
  393.     if(tempHandle != nil) DisposHandle(tempHandle);
  394.     if(source.dataHandle != nil) AEDisposeDesc(&source);
  395.     if(gASComponent != 0) CloseComponent(gASComponent);    
  396.     
  397.     // Restore res file and close our script file
  398.     UseResFile(curResFile);
  399.     CloseResFile(ourFileRef);
  400.     return theErr;
  401. }
  402.  
  403. OSErr DisplayScriptFromFile    (FSSpec theFileToEdit, DialogPtr theDialog, 
  404.                                 ComponentInstance gASComponent,
  405.                                 Boolean *SaveAsCompiled)
  406. {
  407.     OSAID                    resultingID = 0;
  408.     long                    modeFlags = 0;
  409.     Str255                     tempString;
  410.     short                    iType;
  411.     Handle                    iHandle;
  412.     Rect                    iRect;
  413.     short                    ourFileRef = -1;
  414.     Handle                    tempHandle = nil;
  415.     OSErr                    theErr = noErr;
  416.     OSAError                theOSAErr = noErr;
  417.     AEDesc                    source, resultingSourceData;
  418.     
  419.         ourFileRef = FSpOpenResFile(&theFileToEdit, fsRdWrPerm);
  420.         if(ResError()) {
  421.             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  422.             SetIText(iHandle, "\pCouldn't open file to edit!!");
  423.         }
  424.         else {
  425.             UseResFile(ourFileRef);
  426.     
  427.             tempHandle = Get1Resource(kOSAScriptResourceType, kScriptRezID);
  428.             if(tempHandle == nil)
  429.             {
  430.                 *SaveAsCompiled = false;                // Text script??
  431.                 theErr = AddFileToDesc(theFileToEdit, &source);
  432.                 if(theErr == noErr) {
  433.                     GetIText((Handle)source.dataHandle, tempString);
  434.                     GetDItem(theDialog, kScriptField, &iType, &iHandle, &iRect);
  435.                     SetIText(iHandle, tempString);
  436.                 } 
  437.                 else {
  438.                     GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  439.                     SetIText(iHandle, "\pError reading script text in!");
  440.                 }
  441.                     
  442.                 if(tempHandle != nil) DisposHandle(tempHandle);
  443.                         
  444.                 // Now get the comment, if any
  445.                 tempHandle = Get1Resource(kCommentResType, kCommentRezID);
  446.                 if(tempHandle != nil)
  447.                 {
  448.                     DetachResource(tempHandle);
  449.                     GetIText(tempHandle, tempString);
  450.                     GetDItem(theDialog, kCommentField, &iType, &iHandle, &iRect);
  451.                     SetIText(iHandle, tempString);
  452.                 }
  453.             
  454.                 theErr = theOSAErr;
  455.             }
  456.             else
  457.             {
  458.                 *SaveAsCompiled = true;                // Script is stored as compiled
  459.                 DetachResource(tempHandle);            // Make it a handle
  460.             
  461.                 theErr = AECreateDesc(    kOSAScriptResourceType, (Ptr)*tempHandle, 
  462.                                         (Size)(GetHandleSize(tempHandle)), &source);
  463.             
  464.                 if(theErr != noErr) {
  465.                     GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  466.                     SetIText(iHandle, "\pFailed creating script descriptor!");
  467.                 }
  468.                 else {
  469.                     // Load script in resource into scriptID
  470.                     theOSAErr = OSALoad(    gASComponent,
  471.                                             &source,
  472.                                             modeFlags,
  473.                                             &resultingID);
  474.                     
  475.             
  476.                     if(    theOSAErr != noErr) {
  477.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  478.                         SetIText(iHandle, "\pUnable to load script!");
  479.                     }
  480.                     else {    
  481.                         theOSAErr = OSAGetSource(gASComponent,
  482.                                                  resultingID,
  483.                                                  typeChar,
  484.                                                  &resultingSourceData);
  485.                         if(    theOSAErr != noErr){
  486.                             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  487.                             SetIText(iHandle, "\pUnable get script source!");
  488.                         }    
  489.                         else {
  490.                             // Now add it to the edit item
  491.                             GetIText((Handle)resultingSourceData.dataHandle, tempString);     
  492.                             GetDItem(theDialog, kScriptField, &iType, &iHandle, &iRect);
  493.                             SetIText(iHandle, tempString);
  494.                         }
  495.                         if(tempHandle != nil) DisposHandle(tempHandle);
  496.                         
  497.                         // Now get the comment, if any
  498.                         tempHandle = Get1Resource(kCommentResType, kCommentRezID);
  499.                         if(tempHandle != nil)
  500.                         {
  501.                             DetachResource(tempHandle);
  502.                             GetIText(tempHandle, tempString);
  503.                             GetDItem(theDialog, kCommentField, &iType, &iHandle, &iRect);
  504.                             SetIText(iHandle, tempString);
  505.                         }
  506.                         
  507.                         if(source.dataHandle != nil) {
  508.                             AEDisposeDesc(&source);
  509.                             source.dataHandle = nil;
  510.                         }
  511.                         if(resultingSourceData.dataHandle != nil) {
  512.                             AEDisposeDesc(&resultingSourceData);
  513.                             resultingSourceData.dataHandle = nil;
  514.                         }
  515.                         if(tempHandle != nil) {
  516.                             DisposHandle(tempHandle);
  517.                             tempHandle = nil;
  518.                         }
  519.                     }
  520.                 }
  521.             }
  522.         }
  523.     return theErr;
  524. }    
  525.  
  526. ///////////////////////////////////////////////////////////////////////////////
  527. //
  528. //    EditScript
  529. //  This is where we handle our modal edit script dialog
  530. //    
  531. ///////////////////////////////////////////////////////////////////////////////
  532.  
  533. OSErr    EditScript(    FSSpec theFileToEdit, Boolean directObjectFound)
  534. {
  535.     DialogPtr                theDialog;
  536.     GrafPtr                    savedPort;
  537.     short                    itemHit = 0;
  538.     Handle                    tempHandle = nil;
  539.     AEDesc                    source, resultingSourceData;
  540.     OSErr                    theErr = noErr;
  541.     OSAError                theOSAErr = noErr;
  542.     OSAID                    resultingID = 0, resultingScriptValueID = 0;
  543.     long                    modeFlags = 0;
  544.     Str255                     tempString;
  545.     short                    iType;
  546.     Handle                    iHandle;
  547.     Rect                    iRect;
  548.     short                    ourFileRef = -1, curResFile;
  549.     AEDesc                     result;
  550.     ComponentInstance        gASComponent = 0;
  551.     Boolean                    dirtyField = false, SFOk = false;
  552.     Boolean                 SaveAsCompiled = true;
  553.     
  554.     // open generic component
  555.     gASComponent = OpenDefaultComponent(kOSAComponentType, kOSAGenericScriptingComponentSubtype);
  556.     
  557.     // Check errors here!! 
  558.     if((gASComponent == badComponentInstance) || (gASComponent == badComponentSelector))
  559.         return invalidComponentID;     // Is this the right error??
  560.     
  561.     // Nil out dataHandles
  562.     result.dataHandle = nil;
  563.     source.dataHandle = nil;
  564.     resultingSourceData.dataHandle = nil;
  565.     
  566.     curResFile = CurResFile();
  567.         
  568.     GetPort(&savedPort);
  569.     
  570.     theDialog = GetNewDialog(kMYEDITDIALOG, nil, (WindowPtr)-1);    
  571.         
  572.     if(theDialog == nil)
  573.           return resNotFound;        
  574.    
  575.     SetPort(theDialog);
  576.     
  577.     CenterWindow(theDialog);
  578.     
  579.     InitCursor();            // Should do cursor tracking over edit text fields
  580.     
  581.     // Display script (if any) for file selected
  582.     if(directObjectFound) {
  583.         DisplayScriptFromFile(theFileToEdit, theDialog, gASComponent, &SaveAsCompiled);
  584.     }
  585.     
  586.     ShowWindow(theDialog);
  587.     
  588.     do{
  589.         ModalDialog(MyDlgFilter, &itemHit);
  590.         
  591.         switch(itemHit)
  592.         {
  593.             case kOk:
  594.                 // Clear Result Field
  595.                 GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  596.                 SetIText(iHandle, "\p");
  597.                 
  598.                 /*
  599.                     Compile and store script. We really should ask the user if
  600.                     they really want to save changes but hey, they *DID* say OK!
  601.                 */
  602.                 if(dirtyField) {
  603.                     
  604.                     if(!directObjectFound){
  605.                         // Make a file to write to, call SFPut here
  606.                         UseResFile(curResFile);                // So we get our SFP dialogs
  607.                         SFOk = DoSave(&SaveAsCompiled, "\pUntitled Script", &theFileToEdit);    // Invoke standard put file
  608.                         if(ourFileRef != -1)                // Have we opened the file before??
  609.                             UseResFile(ourFileRef);            // Now use other file if opened before
  610.                         if(SFOk != true) 
  611.                             goto BAILLABEL;    // We're done
  612.                         directObjectFound = true; // Now we have an FSSpec to use
  613.                     }
  614.                     
  615.                     GetDItem(theDialog, kScriptField, &iType, &iHandle, &iRect);
  616.                     GetIText(iHandle, tempString);
  617.                     theErr = AECreateDesc(    typeChar, (Ptr)&tempString[1], 
  618.                                 *tempString, &source);
  619.                     if(SaveAsCompiled)    {        
  620.                         theOSAErr = CompileScript(theDialog, gASComponent, source, &resultingID);
  621.                         ourFileRef = FSpOpenResFile(&theFileToEdit, fsRdWrPerm);
  622.                         if(ResError()) {
  623.                             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  624.                             SetIText(iHandle, "\pUnable to save script!");
  625.                         }
  626.                         
  627.                         UseResFile(ourFileRef);
  628.                     
  629.                         theOSAErr =  OSAStore(        gASComponent, 
  630.                                                     resultingID, 
  631.                                                     kOSAScriptResourceType,
  632.                                                     modeFlags,
  633.                                                     &resultingSourceData);
  634.                         if(    theOSAErr != noErr){
  635.                             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  636.                             SetIText(iHandle, "\pUnable to store script!");
  637.                         }    
  638.                             
  639.                         HLock((Handle)resultingSourceData.dataHandle);
  640.                         
  641.                         // Remove old script resource if any
  642.                         tempHandle = Get1Resource(kOSAScriptResourceType, kScriptRezID);
  643.                         if(tempHandle != nil)
  644.                         {
  645.                             RmveResource(tempHandle);
  646.                             UpdateResFile(ourFileRef);
  647.                         }
  648.                         
  649.                         AddResource((Handle)resultingSourceData.dataHandle, 
  650.                                     kOSAScriptResourceType, kScriptRezID, "\p");
  651.                         if(ResError()){
  652.                             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  653.                             SetIText(iHandle, "\pUnable to add script resource!");
  654.                         }
  655.                         WriteResource((Handle)resultingSourceData.dataHandle);
  656.                         UpdateResFile(ourFileRef);
  657.                         
  658.                         AEDisposeDesc(&source);
  659.                         DetachResource((Handle)resultingSourceData.dataHandle);
  660.                         AEDisposeDesc(&resultingSourceData);
  661.                     }
  662.                     else {    // Save as text
  663.                         // Finish up
  664.                             
  665.                         ourFileRef = FSpOpenResFile(&theFileToEdit, fsRdWrPerm);
  666.                         if(ResError()) {
  667.                             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  668.                             SetIText(iHandle, "\pUnable to save script!");
  669.                         }
  670.                         directObjectFound = true;         // Now we have an FSSpec to use
  671.                         UseResFile(ourFileRef);
  672.                         
  673.                         theErr = AddDescToFile(theFileToEdit, source);
  674.                         AEDisposeDesc(&source);
  675.                     }
  676.                     // Remove old comment resource if any
  677.                     tempHandle = Get1Resource(kCommentResType, kCommentRezID);
  678.                     if(tempHandle != nil)
  679.                     {
  680.                         RmveResource(tempHandle);
  681.                         UpdateResFile(ourFileRef);
  682.                     }
  683.  
  684.                     // Now add the comment
  685.                     
  686.                     GetDItem(theDialog, kCommentField, &iType, &iHandle, &iRect);
  687.                     GetIText(iHandle, tempString);
  688.                     theErr = AECreateDesc(    typeChar, (Ptr)&tempString[1], 
  689.                                             *tempString, &source);
  690.                     
  691.                     if(theErr != noErr){
  692.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  693.                         SetIText(iHandle, "\pAECreateDesc Failed for comment rez!");
  694.                     }
  695.                     HLock((Handle)source.dataHandle);
  696.                     tempHandle = (Handle)source.dataHandle;
  697.                     HandToHand(&tempHandle);
  698.                     AddResource(tempHandle, kCommentResType, kCommentRezID, "\p");
  699.  
  700.                     if(ResError()){
  701.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  702.                         SetIText(iHandle, "\pUnable to add comment resource!");
  703.                     }
  704.                     WriteResource(tempHandle);
  705.                     UpdateResFile(ourFileRef);
  706.                     if(tempHandle != nil) ReleaseResource(tempHandle);
  707.                 }
  708.                 break;
  709.             case kCancel:
  710.                 /*
  711.                     Cancel so bail. If the script was dirty we really should ask the user if
  712.                     they really want to save changes but hey, YOU can do it if you want!
  713.                 */
  714.                 break;
  715.             case kExecute:
  716.                 // Clear Result Field
  717.                 GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  718.                 SetIText(iHandle, "\p");
  719.                 
  720.                 // Compile and select errors if any
  721.                 GetDItem(theDialog, kScriptField, &iType, &iHandle, &iRect);
  722.                 GetIText(iHandle, tempString);
  723.                 theErr = AECreateDesc(    typeChar, (Ptr)&tempString[1], 
  724.                             *tempString, &source);
  725.  
  726.                 theOSAErr =  OSACompileExecute(    gASComponent,
  727.                                                   &source,
  728.                                                   kOSANullScript,
  729.                                                   modeFlags,
  730.                                                   &resultingScriptValueID);
  731.                 if(theOSAErr != noErr) {
  732.                     if(theOSAErr == errOSAScriptError) {
  733.                         theOSAErr = OSAScriptError(gASComponent, kOSAErrorMessage,
  734.                                                     typeChar, &resultingSourceData);
  735.                         if(    theOSAErr != noErr) {
  736.                             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  737.                             SetIText(iHandle, "\pUnable to get error from scripting System");
  738.                         }
  739.                         else {    
  740.                             GetIText((Handle)resultingSourceData.dataHandle, tempString);
  741.                             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  742.                             SetIText(iHandle, tempString);
  743.                         }
  744.                     }
  745.                     else {
  746.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  747.                         SetIText(iHandle, "\pWasn't errOSAScriptError!");
  748.                     }
  749.                     itemHit = kCycleAgain;
  750.                 }
  751.                 else {
  752.                     theOSAErr = OSADisplay(    gASComponent,
  753.                                             resultingScriptValueID,
  754.                                             typeChar,
  755.                                             modeFlags,
  756.                                             &result);
  757.                                             
  758.                     GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  759.                     GetIText((Handle)result.dataHandle, tempString);
  760.                     SetIText(iHandle, tempString);
  761.                     theErr = theOSAErr;
  762.                 }    
  763.                 break;
  764.             
  765.             case kSaveAs:
  766.                 // Clear Result Field
  767.                 GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  768.                 SetIText(iHandle, "\p");
  769.                 
  770.                 // Save file
  771.                 UseResFile(curResFile);
  772.                 if(directObjectFound)
  773.                     SFOk = DoSave(&SaveAsCompiled, (Str255)theFileToEdit.name, &theFileToEdit); // Invoke standard put file
  774.                 else
  775.                     SFOk = DoSave(&SaveAsCompiled, "\pUntitled Script", &theFileToEdit);
  776.                 if(SFOk != true)
  777.                     break;
  778.                 else
  779.                     directObjectFound = true;         // Now we have an FSSpec to use    
  780.                 if(ourFileRef != -1)
  781.                     UseResFile(ourFileRef);
  782.                     
  783.                 // Put source text into descriptor
  784.                 GetDItem(theDialog, kScriptField, &iType, &iHandle, &iRect);
  785.                 GetIText(iHandle, tempString);
  786.                 theErr = AECreateDesc(    typeChar, (Ptr)&tempString[1], 
  787.                             *tempString, &source);
  788.                             
  789.                 if(SaveAsCompiled) {
  790.                     theOSAErr = CompileScript(theDialog, gASComponent, source, &resultingID);
  791.  
  792.                     ourFileRef = FSpOpenResFile(&theFileToEdit, fsRdWrPerm);
  793.                     if(ResError()){
  794.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  795.                         SetIText(iHandle, "\pUnable to open script file!");
  796.                     }
  797.                     
  798.                     UseResFile(ourFileRef);
  799.  
  800.                     theOSAErr =  OSAStore(        gASComponent, 
  801.                                                 resultingID, 
  802.                                                 kOSAScriptResourceType,
  803.                                                 modeFlags,
  804.                                                 &resultingSourceData);
  805.                     if(    theOSAErr != noErr){
  806.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  807.                         SetIText(iHandle, "\pUnable to store script!");
  808.                     }    
  809.                         
  810.                     HLock((Handle)resultingSourceData.dataHandle);
  811.                     
  812.                     tempHandle = Get1Resource(kOSAScriptResourceType, kScriptRezID);
  813.                     if(tempHandle != nil) {
  814.                         RmveResource(tempHandle);
  815.                         UpdateResFile(ourFileRef);
  816.                     }
  817.                     
  818.                     AddResource((Handle)resultingSourceData.dataHandle, 
  819.                                 kOSAScriptResourceType, kScriptRezID, "\p");
  820.                     if(ResError()){
  821.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  822.                         SetIText(iHandle, "\pUnable to add script resource!");
  823.                     }
  824.                     WriteResource((Handle)resultingSourceData.dataHandle);
  825.                     UpdateResFile(ourFileRef);
  826.                     DetachResource((Handle)resultingSourceData.dataHandle);
  827.                     AEDisposeDesc(&source);
  828.                     AEDisposeDesc(&resultingSourceData);
  829.                 }
  830.                 else {
  831.                     
  832.                     // We need to do this so we can add the comment resource later
  833.                     ourFileRef = FSpOpenResFile(&theFileToEdit, fsRdWrPerm);
  834.                     if(ResError()){
  835.                         GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  836.                         SetIText(iHandle, "\pUnable to open script file!");
  837.                     }
  838.                     UseResFile(ourFileRef);
  839.  
  840.                     theErr = AddDescToFile(theFileToEdit, source);
  841.                     AEDisposeDesc(&source);
  842.                 }
  843.                 // Remove old comment resource if any
  844.                 tempHandle = Get1Resource(kCommentResType, kCommentRezID);
  845.                 if(tempHandle != nil)
  846.                 {
  847.                     RmveResource(tempHandle);
  848.                     UpdateResFile(ourFileRef);
  849.                 }    
  850.                 
  851.                 // Now add the comment    
  852.                 GetDItem(theDialog, kCommentField, &iType, &iHandle, &iRect);
  853.                 GetIText(iHandle, tempString);
  854.                 theErr = AECreateDesc(    typeChar, (Ptr)&tempString[1], 
  855.                             *tempString, &source);
  856.                 if(theErr != noErr){
  857.                     GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  858.                     SetIText(iHandle, "\pAECreateDesc Failed for comment rez!");
  859.                 }
  860.                 HLock((Handle)source.dataHandle);
  861.                 tempHandle = (Handle)source.dataHandle;
  862.                 HandToHand(&tempHandle);
  863.                 AddResource(tempHandle, kCommentResType, kCommentRezID, "\p");
  864.  
  865.                 if(ResError()){
  866.                     GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  867.                     SetIText(iHandle, "\pUnable to add comment resource!");
  868.                 }
  869.                 WriteResource((Handle)tempHandle);
  870.                 UpdateResFile(ourFileRef);
  871.                 dirtyField = false;
  872.                 if(tempHandle != nil) ReleaseResource(tempHandle);
  873.                 UseResFile(curResFile);
  874.                 CloseResFile(ourFileRef);
  875.                 break;
  876.             
  877.             case kResultField:;    // We use hits in the dialog items to 
  878.             case kScriptField:;    // indicate a dirty script that needs to
  879.             case kCommentField: // be saved to disk.
  880.                 dirtyField = true;
  881.                 break;
  882.                 
  883.             default:
  884.                 break;
  885.         }
  886.     }while ((itemHit != ok) && (itemHit != cancel));
  887.     
  888.     BAILLABEL:;
  889.     DisposDialog(theDialog);
  890.     
  891.     UseResFile(curResFile);
  892.     CloseResFile(ourFileRef);
  893.     
  894.     SetPort(savedPort);
  895.     
  896.     if(resultingScriptValueID != 0) OSADispose(    gASComponent, resultingScriptValueID);
  897.     if(resultingID != 0) OSADispose(    gASComponent, resultingID);
  898.     if(gASComponent != 0) CloseComponent(gASComponent);
  899.     if(tempHandle != nil) ReleaseResource(tempHandle);
  900.     if(source.dataHandle != nil) AEDisposeDesc(&source);
  901.     if(result.dataHandle != nil) AEDisposeDesc(&result);
  902.     if(resultingSourceData.dataHandle != nil) AEDisposeDesc(&resultingSourceData);
  903.     
  904.     return theErr;
  905. }
  906.  
  907. OSAError CompileScript(DialogPtr theDialog, ComponentInstance gASComponent, AEDesc source, OSAID *resultingID)
  908. {
  909.     OSAError     theOSAErr, theCompileErr;
  910.     AEDesc        resultingSourceData;
  911.     short        iType;
  912.     Handle        iHandle = nil;
  913.     Rect        iRect;
  914.     Str255        tempString;
  915.     
  916.     resultingSourceData.dataHandle = nil;
  917.     theCompileErr =  OSACompile(    gASComponent,
  918.                                     &source,
  919.                                     kOSAModeCompileIntoContext,
  920.                                     resultingID);
  921.     if(    theCompileErr != noErr) {
  922.         if(theCompileErr == errOSAScriptError) {
  923.             // Display error in result field 
  924.             theOSAErr = OSAScriptError(gASComponent, kOSAErrorMessage, typeChar, &resultingSourceData);
  925.             if(    theOSAErr != noErr) {
  926.                 GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  927.                 SetIText(iHandle, "\pUnable to get error from scripting System");
  928.             }
  929.             else {    
  930.                 GetIText((Handle)resultingSourceData.dataHandle, tempString);
  931.                 GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  932.                 SetIText(iHandle, tempString);
  933.             }
  934.         }
  935.         else {
  936.             GetDItem(theDialog, kResultField, &iType, &iHandle, &iRect);
  937.             SetIText(iHandle, "\pWasn't errOSAScriptError!");
  938.         }
  939.     }
  940.     if(resultingSourceData.dataHandle != nil) AEDisposeDesc(&resultingSourceData);
  941.     return theCompileErr;
  942. }
  943.  
  944. ///////////////////////////////////////////////////////////////////////////////
  945. //
  946. //    mySFPHook
  947. //  This is the sfp hook where we set up and take care of our custom dialog 
  948. //    items. MyData is a Boolean which if true, indicates to dave as compiled
  949. //    script.
  950. //    
  951. ///////////////////////////////////////////////////////////////////////////////
  952.  
  953. pascal short mySFPHook(short item, DialogPtr theDialog, void *myData)
  954. {
  955.     short                    iType;
  956.     Handle                    iHandle = nil;
  957.     Rect                    iRect;
  958.     
  959.     switch(item) {
  960.         case sfHookFirstCall:
  961.             GetDItem(theDialog, kSaveCompiled, &iType, &iHandle, &iRect);
  962.             if(iHandle != nil) {
  963.                 if(*(Boolean*)myData) {
  964.                     GetDItem(theDialog, kSaveCompiled, &iType, &iHandle, &iRect);
  965.                     SetCtlValue((ControlHandle)iHandle, 1);
  966.                     GetDItem(theDialog, kSaveText, &iType, &iHandle, &iRect);
  967.                     SetCtlValue((ControlHandle)iHandle, 0);
  968.                     *(Boolean*)myData = true;
  969.                 }
  970.                 else {
  971.                     GetDItem(theDialog, kSaveCompiled, &iType, &iHandle, &iRect);
  972.                     SetCtlValue((ControlHandle)iHandle, 0);
  973.                     GetDItem(theDialog, kSaveText, &iType, &iHandle, &iRect);
  974.                     SetCtlValue((ControlHandle)iHandle, 1);
  975.                     *(Boolean*)myData = false;
  976.                 }
  977.             }
  978.             break;
  979.         case kSaveCompiled :
  980.             GetDItem(theDialog, kSaveCompiled, &iType, &iHandle, &iRect);
  981.             SetCtlValue((ControlHandle)iHandle, 1);
  982.             GetDItem(theDialog, kSaveText, &iType, &iHandle, &iRect);
  983.             SetCtlValue((ControlHandle)iHandle, 0);
  984.             *(Boolean*)myData = true;
  985.             break; 
  986.         case kSaveText:
  987.             GetDItem(theDialog, kSaveCompiled, &iType, &iHandle, &iRect);
  988.             SetCtlValue((ControlHandle)iHandle, 0);
  989.             GetDItem(theDialog, kSaveText, &iType, &iHandle, &iRect);
  990.             SetCtlValue((ControlHandle)iHandle, 1);
  991.             *(Boolean*)myData = false;
  992.             break;
  993.         
  994.         default:
  995.             break;
  996.     }
  997.     return item;
  998. }
  999.  
  1000. ///////////////////////////////////////////////////////////////////////////////
  1001. //
  1002. //    DoSave
  1003. //  Wrapper for CustomPutFile
  1004. //    
  1005. ///////////////////////////////////////////////////////////////////////////////
  1006.  
  1007. Boolean DoSave(Boolean *SaveAsCompiled, Str255 scriptName, FSSpec *theFileToEdit)
  1008. {
  1009.     OSErr                theErr = noErr;
  1010.     Point                 where;
  1011.     StandardFileReply     theSFR;
  1012.     SetPt(&where, -1, -1);
  1013.     
  1014.     CustomPutFile(    "\pSave Script As:", scriptName, &theSFR, kMySPutRsrc, 
  1015.                     where, mySFPHook, nil, nil, nil, SaveAsCompiled);
  1016.     if(theSFR.sfGood != true)
  1017.         return false;
  1018.     if(theSFR.sfReplacing) {
  1019.         theErr = FSpDelete(&theSFR.sfFile);                                    
  1020.         if(theErr == noErr)
  1021.             FSpCreateResFile(&theSFR.sfFile, kToySurprise, *SaveAsCompiled ? kCompiledScript : kTextScript, theSFR.sfScript);
  1022.     }
  1023.     else
  1024.         FSpCreateResFile(&theSFR.sfFile, kToySurprise, *SaveAsCompiled ? kCompiledScript : kTextScript, theSFR.sfScript);
  1025.     *theFileToEdit = theSFR.sfFile;
  1026.     return true;
  1027. }
  1028.  
  1029. ///////////////////////////////////////////////////////////////////////////////
  1030. //
  1031. //    CenterWindow
  1032. //  Could use the System 7 autocentering code, but old habits die hard.
  1033. //    
  1034. ///////////////////////////////////////////////////////////////////////////////
  1035.  
  1036. void CenterWindow(DialogPtr theDialog)
  1037. {
  1038.     Rect         screenRect,
  1039.                 dialogRect;
  1040.     short        vPt = 0, hPt = 0;
  1041.     
  1042.     dialogRect = theDialog->portRect;
  1043.     
  1044.     screenRect = ReturnScreenRect();
  1045.     
  1046.     vPt = ((screenRect.bottom - screenRect.top) - (dialogRect.bottom - dialogRect.top))/3;  // Move to top 1/3
  1047.     hPt = ((screenRect.right - screenRect.left) - (dialogRect.right - dialogRect.left))/2;
  1048.     MoveWindow(theDialog, hPt, vPt - kSenceOfDecorum, false);
  1049. }
  1050.  
  1051. ///////////////////////////////////////////////////////////////////////////////
  1052. //
  1053. //    ReturnScreenRect
  1054. //  Guess what this does??
  1055. //    
  1056. ///////////////////////////////////////////////////////////////////////////////
  1057.  
  1058. Rect ReturnScreenRect()
  1059. {
  1060.     GrafPtr    myPort;
  1061.     
  1062.     GetWMgrPort(&myPort);
  1063.     return (myPort->portRect);//(*MainDevice)->gdRect;
  1064. }
  1065.  
  1066. ///////////////////////////////////////////////////////////////////////////////
  1067. //
  1068. //    MyDlgFilter
  1069. //  Dialog filter for our edit dialog.
  1070. //    Here's where we handle the command period and escape key stuff. We really
  1071. //  don't need to do this since in System 7 there are new dailog manager routines
  1072. //    that do this for us. Shucks!
  1073. //    
  1074. ///////////////////////////////////////////////////////////////////////////////
  1075.  
  1076. pascal Boolean MyDlgFilter(DialogPtr theDlg, EventRecord *theEventRec, short *itemHit)
  1077. {
  1078.     #pragma unused (theDlg)
  1079.     pascal Boolean IsCmdChar(const EventRecord *, short test)
  1080.         = {0x2F3C,0x8206,0xFFD0,0xA8B5};
  1081.                     
  1082.     if( theEventRec->what==keyDown || theEventRec->what==autoKey ) 
  1083.     {
  1084.         char c = theEventRec->message&0xFF;
  1085.         if( IsCmdChar(theEventRec,'.') )
  1086.         {
  1087.             *itemHit = cancel;            // Cmd-Period hit!
  1088.             return (true);
  1089.         }    
  1090.         else 
  1091.             if( c==0x1B && (theEventRec->message&0xFF00)==0x3500 )
  1092.             {
  1093.                 *itemHit = cancel;        // Esc key hit!
  1094.                 return (true);
  1095.             }
  1096.     }    
  1097.     return (false);
  1098. }